package com.example.test15middleware.idTest;

import com.example.test15middleware.config.SequenceService;
import com.example.test15middleware.config.TicketNoGenerator;
import org.junit.jupiter.api.Test;
import org.springframework.boot.test.context.SpringBootTest;
import org.springframework.data.redis.core.RedisTemplate;
import redis.clients.jedis.Jedis;
import redis.clients.jedis.Response;
import redis.clients.jedis.Transaction;

import javax.annotation.Resource;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * @Author: fxy
 * @Date: 2022/07/04/14:11
 * @Description:
 */
@SpringBootTest
public class RedisGenerateId {

    @Resource
    TicketNoGenerator ticketNoGenerator;

    @Resource
    RedisTemplate redisTemplate;

    @Resource
    SequenceService sequenceService;
    @Test
    public void generateId(){
        for(int i = 0;i<20;i++){
            new Thread(()->{
                String s = ticketNoGenerator.generateTicketNo();
                System.out.println(s);
            }).start();

        }

        try {
            Thread.sleep(10000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }

    @Test
    public void generateId2(){
        for(int i = 0;i<100;i++){
            String s = ticketNoGenerator.generateTicketNo();
            System.out.println(s);
        }
    }

    @Test
    public void generateId3(){
        for(int i = 0;i<100;i++){
            String s = sequenceService.getOrderNo("DEVICE");
            System.out.println(s);
        }
    }

    @Test
    public void generateId4() throws InterruptedException {
        for(int i = 0;i<200;i++){
            new Thread(()->{
                String s = sequenceService.getOrderNo("DEVICE");
                System.out.println(s);
            }).start();

        }

        Thread.sleep(10000);
    }
    //秒杀测试
    @Test
    public  void secondKill() {
        String redisKey = "lock";
        ExecutorService executorService = Executors.newFixedThreadPool(20);//20个线程
        try {//初始化
            Jedis jedis = new Jedis("127.0.0.1", 6379);
            // 初始值
            jedis.set(redisKey, "0");
            jedis.close();
        } catch (Exception e) {
            e.printStackTrace();
        }

        for (int i = 0; i < 1000; i++) {//尝试1000次
            executorService.execute(() -> {
                Jedis jedis1 = new Jedis("127.0.0.1", 6379);
                try {
                    jedis1.watch(redisKey);
                    String redisValue = jedis1.get(redisKey);
                    int valInteger = Integer.valueOf(redisValue);
                    String userInfo = UUID.randomUUID().toString();
                    // 没有秒完
                    if (valInteger < 20) {//redisKey
                        Transaction tx = jedis1.multi();//开启事务
                        tx.incr(redisKey);//自增
                        List list = tx.exec();//提交事务，如果返回nil则说明执行失败，因为我watch了的，只要执行失败，则
                        // 进来发现东西还有，秒杀成功
                        if (list != null && list.size() > 0) {
                            System.out.println("用户：" + userInfo + "，秒杀成功！当前成功人数：" + (valInteger + 1));
                        }else {//执行结果不是OK，说明被修改了，被别人抢了
                            System.out.println("用户：" + userInfo + "，秒杀失败");
                        }
                    }else {//东西秒完了
                        System.out.println("已经有20人秒杀成功，秒杀结束");
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                } finally {//关闭redis
                    jedis1.close();
                }
            });
        }
        executorService.shutdown();//关闭线程池
    }

    /**
     * 使用redis事务在多线程下保证获取唯一值
     */
    @Test
    public void JedisTransaction(){
        String key = "yun-test:JedisTransaction";
        Jedis jedis = new Jedis("127.0.0.1", 6379);
        // 初始值
        jedis.set(key, "0");
        jedis.close();
        for(int i=0;i<100;i++){
            new Thread(()->{
                Jedis jedis1 = new Jedis("127.0.0.1", 6379);

                try {
                    while(true){
                        jedis1.watch(key);
                        Transaction multi = jedis1.multi();
                        multi.incr(key);
                        Response<String> stringResponse = multi.get(key);
                        List list = multi.exec();
                        if (list != null && list.size() > 0) {
                            System.out.println("自增成功：当前值="+stringResponse.get());
                            break;
                        }else {//执行结果不是OK，说明被修改了，被别人抢了
                            System.out.println("自增失败");
                        }
                    }
                }catch (Exception e){
                    e.printStackTrace();
                }finally {
                    jedis1.close();
                }
            }).start();
        }
    }


}
